#include "plan_thread.h"

#ifdef WIN32
#define usleep(x) Sleep(x)
#endif

#include "pfunc.h"
#include "Log.h"

#include "business_def.h"
#include "verifyforcontrolcache.h"
#include "delay_plan_thread.h"

namespace G_VALUE {
	unsigned int planUpT=0;
};

PlanThread::PlanThread(void) 
	: Strategy()
	, running(true)
	, is_Verification(false)
	, ptr_vcc(VerifyForControlCache::getInstance())
	, ptr_delay_plan(NULL)
	, timePlan(static_cast<unsigned int>(time(NULL)))
	, socket_write_queue(QueueDataSingle<DataToGather> ::getInstance())
{
	is_Verification = pbdef->getVerificationFunc();
	plans = pbdef->getPlans();
};

PlanThread::~PlanThread(void)
{
	running = false;
	ptr_delay_plan = NULL;
};

void* PlanThread::run()
{
	unsigned int planSize = static_cast<unsigned int>(plans.size());
	unsigned int curTimeSec = 0;
	while (running)
	{
		G_VALUE::planUpT = static_cast<unsigned int>(time(NULL));
		for(unsigned int i=0; i<planSize; ++i)
		//for (std::vector<Plan>::iterator it = plans.begin();it!=plans.end();it++)
		{
			//执行间隔条件,执行成功后需间隔一段时间才能再次进行条件巡检
			if (plans[i].planAtt.planInterval>0
				&&(plans[i].planAtt.planSuccessFlag+ plans[i].planAtt.planInterval)>static_cast<unsigned long>(pyfree::getClockTime())) 
			{
				continue;
			}
			curTimeSec = static_cast<unsigned int>(time(NULL));
			switch (plans[i].planAtt.planType)
			{
			case 1://定时
			{
				if (mapCurTimes(plans[i].ptimes)
					&& (timePlan + plans[i].planAtt.planEffect)<curTimeSec)
				{
					doCmd(plans[i].planCmds);
					if (plans[i].planAtt.planInterval > 0)
					{
						plans[i].planAtt.planSuccessFlag = static_cast<unsigned long>(pyfree::getClockTime());
					}
				}
			}
				break;
			case 2://定期
			{
				if (mapSleepTime(plans[i].timeVS,plans[i].psleep)
					&& (timePlan + plans[i].planAtt.planEffect)<curTimeSec)
				{
					doCmd(plans[i].planCmds);
					if (plans[i].planAtt.planInterval > 0)
					{
						plans[i].planAtt.planSuccessFlag = static_cast<unsigned long>(pyfree::getClockTime());
					}
				}
			}
				break;
			case 3://条件
			{
				if (conditionJude(plans[i].timeVS,plans[i].plancons)
					&& (timePlan + plans[i].planAtt.planEffect)<curTimeSec)
				{
					doCmd(plans[i].planCmds);
					if (plans[i].planAtt.planInterval > 0)
					{
						plans[i].planAtt.planSuccessFlag = static_cast<unsigned long>(pyfree::getClockTime());
					}
					//printf("conditionJude success!\n");
				}
			}
				break;
			case 4://启动任务添加时间范围约束,约定其启动后waitSec秒内到waitSec+60秒内执行
				if (!plans[i].pFStart.execFlag
					&& (timePlan + plans[i].pFStart.waitSec)<curTimeSec
					&& (timePlan + plans[i].pFStart.waitSec+60)>curTimeSec
					&& mapStartTime(plans[i].timeVS))
				{
					plans[i].pFStart.execFlag = true;
					doCmd(plans[i].planCmds);
					if (plans[i].planAtt.planInterval > 0)
					{
						plans[i].planAtt.planSuccessFlag = static_cast<unsigned long>(pyfree::getClockTime());
					}
				}
				break;
			default:
				break;
			}
		}
		usleep(10);
	}
	return NULL;
};

void PlanThread::setDelayPlanThread(DelayPlanThread *ptr_)
{
	ptr_delay_plan = ptr_;
};

void PlanThread::doCmd(std::vector<PlanCMD> planCmds)
{
	int index = 1;
	for (std::vector<PlanCMD>::iterator it = planCmds.begin();
		it != planCmds.end(); ++it)
	{
		unsigned long taskID = pyfree::getTaskIDFromDateTime(index);
		float m_OldVal_f = it->val;//期望结果值
		if (it->dDevID > 0)
		{
			pbdef->getValue(it->dDevID, it->dPID, m_OldVal_f);//获取依赖点的当前数值
		}
		index += 1;//防止处理过快时编号重复
		PFrom _pfrom;
		if (pbdef->getFromInfo(it->devID,it->pID,_pfrom))
		{
			float m_RealVal_f = m_OldVal_f;//实际下控值需要通过点的基准值和系数演算
			if (OnSet == it->exeType) 
			{
				//获取实际计算值,虚拟点无基准值和系数
				pbdef->getCValue(it->devID, static_cast<unsigned int>(it->pID), m_RealVal_f);
			}
			if (it->timedelay > 0) 
			{
				unsigned long _usec = static_cast<unsigned long>(pyfree::getClockTime());
				DataToGather wd(_pfrom.ipLong, it->exeType, _pfrom.pID, _pfrom.pType, m_RealVal_f
					, _usec+ static_cast<unsigned long>(it->timedelay),it->desc, taskID);
				addDelayExec(wd);//防护阻隔到延时指令的执行,迁移延时指令执行到新线程处理

				CLogger::createInstance()->Log(MsgInfo
					, "TaskID[%lu] and down_node[1-1] Create delay plan cmd(%s),time(%s)"
					",execType(%d),devID(%ld),pID(%d),val(%.2f),delaySleep(%d)"
					, taskID, it->desc.c_str(), pyfree::getCurrentTime().c_str()
					, static_cast<int>(it->exeType),it->devID, it->pID, m_OldVal_f
					, it->timedelay);
				//
				if (OnSet == it->exeType && is_Verification)
				{
					VerificationCache vit;
					vit.execTime = pyfree::getCurrentTimeByFormat("%04d%02d%02dT%02d%02d%02dZ");
					vit.taskID = taskID;
					vit.taskDesc = it->desc;
					vit.devID = static_cast<unsigned long>(it->devID);
					vit.devDesc = _pfrom.devDesc;
					vit.pID = static_cast<unsigned long>(it->pID);
					vit.pDesc = _pfrom.pDesc;
					vit.pType = static_cast<unsigned int>(_pfrom.pType);
					vit.val = m_OldVal_f;
					vit.limitTimeForCheck = static_cast<unsigned int>(time(NULL)) + it->vtime + (it->timedelay / 1000);
					vit.eway_ = _pfrom.eway;
					ptr_vcc->addVerifyData(vit);
				}
			}
			else 
			{
				DataToGather wd(_pfrom.ipLong, it->exeType, _pfrom.pID, _pfrom.pType, m_RealVal_f
					,0,it->desc, taskID);
				socket_write_queue->add(wd);

				CLogger::createInstance()->Log(MsgInfo
					, "TaskID[%lu] and down_node[1] setPValue from plan cmd(%s),time(%s)"
					",execType(%d),devID(%ld),pID(%d),val(%.2f)"
					",ip(%lu,%s),pID(%d),pType(%d),val(%.3f) and wait(%d)ms"
					, taskID, it->desc.c_str(), pyfree::getCurrentTime().c_str()
					, static_cast<int>(it->exeType),it->devID, it->pID, m_OldVal_f
					, _pfrom.ipLong, _pfrom.ipStr.c_str()
					, _pfrom.pID, static_cast<int>(_pfrom.pType), m_RealVal_f
					, it->waitT);
				//后续优化时,可以(it->timedelay>0)态势的合并
				if (OnSet == it->exeType && is_Verification)
				{
					VerificationCache vit;
					vit.execTime = pyfree::getCurrentTimeByFormat("%04d%02d%02dT%02d%02d%02dZ");
					vit.taskID = taskID;
					vit.taskDesc = it->desc;
					vit.devID = static_cast<unsigned long>(it->devID);
					vit.devDesc = _pfrom.devDesc;
					vit.pID = static_cast<unsigned long>(it->pID);
					vit.pDesc = _pfrom.pDesc;
					vit.pType = static_cast<unsigned int>(_pfrom.pType);
					vit.val = m_OldVal_f;
					vit.limitTimeForCheck = static_cast<unsigned int>(time(NULL)) + it->vtime;	//当前设定为5秒后校验下控返回状态,后续可以读取每个指令设定配置
					vit.eway_ = _pfrom.eway;
					ptr_vcc->addVerifyData(vit);
				}
				if (it->waitT>0) 
				{
#ifdef WIN32
					Sleep(it->waitT);
#else
					usleep(1000*(it->waitT));
#endif
				}
			}
		}
		else 
		{//no map point for virtual point
			if (it->timedelay > 0) 
			{
				unsigned long _usec = static_cast<unsigned long>(pyfree::getClockTime());
				DataToGather wd(it->devID, it->exeType, it->pID, it->pType, m_OldVal_f
					, _usec + static_cast<unsigned long>(it->timedelay), it->desc, taskID);
				wd.virtualP = true;
				addDelayExec(wd);

				CLogger::createInstance()->Log(MsgInfo
					, "TaskID[%lu] and down_node[1-1] Create delay plan cmd(%s)(virtual-point),time(%s)"
					",execType(%d),devID(%ld),pID(%d),val(%.2f),delaySleep(%d)"
					, taskID, it->desc.c_str(), pyfree::getCurrentTime().c_str()
					, static_cast<int>(it->exeType), it->devID, it->pID, m_OldVal_f
					, it->timedelay);
			}
			else
			{
				PValueRet pret(m_OldVal_f);
				pbdef->setHValue(it->devID, static_cast<unsigned int>(it->pID), pret,true);
				CLogger::createInstance()->Log(MsgInfo
					, "TaskID[%lu] and down_node[1] setPValue(virtual-point) from plan CMD "
					"and down_node[0],time(%s),devID(%ld),pID(%ld),val(%.3f)"
					",ditect set val to virtual ponit control"
					, taskID, pyfree::getCurrentTime().c_str()
					, it->devID, it->pID, pret.val_actual);
				if (it->waitT>0) 
				{
#ifdef WIN32
					Sleep(it->waitT);
#else
					usleep(1000 * (it->waitT));
#endif
				}
			}
		}
	}
};

void PlanThread::addDelayExec(DataToGather wd)
{
	if (NULL != ptr_delay_plan)
	{
		ptr_delay_plan->addDelayExec(wd);
	}
};
